package com.xgzit.xgzmall.member.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xgzit.common.utils.HttpUtils;
import com.xgzit.xgzmall.member.entity.MemberLevelEntity;
import com.xgzit.xgzmall.member.exception.EmailExistException;
import com.xgzit.xgzmall.member.exception.PhoneExistException;
import com.xgzit.xgzmall.member.exception.UserNameExistException;
import com.xgzit.xgzmall.member.service.MemberLevelService;
import com.xgzit.xgzmall.member.vo.SocialUserVo;
import com.xgzit.xgzmall.member.vo.UserLoginVo;
import com.xgzit.xgzmall.member.vo.UserRegisterVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xgzit.common.utils.PageUtils;
import com.xgzit.common.utils.Query;

import com.xgzit.xgzmall.member.dao.MemberDao;
import com.xgzit.xgzmall.member.entity.MemberEntity;
import com.xgzit.xgzmall.member.service.MemberService;

/**
 * @author xushuai
 */
@Slf4j
@Service("memberService")
public class MemberServiceImpl extends ServiceImpl<MemberDao, MemberEntity> implements MemberService {

    @Autowired
    MemberLevelService memberLevelService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<MemberEntity> page = this.page(
                new Query<MemberEntity>().getPage(params),
                new QueryWrapper<MemberEntity>()
        );
        return new PageUtils(page);
    }

    @Override
    public void register(UserRegisterVo vo) {
        MemberEntity entity = new MemberEntity();
        // 默认等级
        MemberLevelEntity memberLevelEntity = memberLevelService.getDefaultLevel();
        entity.setLevelId(memberLevelEntity.getId());
        // 检查用户名或者手机号是否唯一, 使用异常机制 让上层感知异常
        entity.setUsername(vo.getUserName());
        entity.setMobile(vo.getPhone());
        entity.setNickname(vo.getUserName());
        this.checkUserNameUnique(vo.getUserName());
        this.checkPhoneUnique(vo.getPhone());
        // 密码要加密存储
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String encode = passwordEncoder.encode(vo.getPassword());
        entity.setPassword(encode);
        // 验证密码使用 passwordEncoder.matches("用户输入", "数据库保存的密码");
        this.save(entity);
    }

    @Override
    public void checkUserNameUnique(String userName) throws UserNameExistException{
        int count = this.count(new LambdaQueryWrapper<MemberEntity>()
                .eq(MemberEntity::getUsername, userName));
        if (count>0) {
            throw new UserNameExistException();
        }
    }

    @Override
    public void checkEmailUnique(String email) throws EmailExistException{
        int count = this.count(new LambdaQueryWrapper<MemberEntity>()
                .eq(MemberEntity::getEmail, email));
        if (count>0) {
            throw new EmailExistException();
        }

    }

    @Override
    public void checkPhoneUnique(String phone) throws PhoneExistException{
        int count = this.count(new LambdaQueryWrapper<MemberEntity>()
                .eq(MemberEntity::getMobile, phone));
        if (count>0) {
           throw new PhoneExistException();
        }
    }

    @Override
    public MemberEntity login(UserLoginVo vo) {
        String loginAccount = vo.getLoginAccount();
        String password = vo.getPassword();
        // WHERE (username = ? OR email = ? OR mobile = ?)
        MemberEntity one = this.getOne(new LambdaQueryWrapper<MemberEntity>()
                        .eq(MemberEntity::getUsername, loginAccount)
                        .or().eq(MemberEntity::getEmail, loginAccount)
                        .or().eq(MemberEntity::getMobile, loginAccount));

        if (Objects.nonNull(one)){
            // 密码匹配
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            boolean matches = passwordEncoder.matches(password, one.getPassword());
            if (matches){
                log.info("登录成功！");
                return one;
            }
            log.error("密码错误！");
        }
        log.error("用户名不存在！");
        return null;
    }

    @Override
    public MemberEntity login(SocialUserVo vo) {
        // 登录和注册 合并逻辑
        String uid = vo.getUid();
        // 判断当前社交用户是否在系统中注册过
        MemberEntity one = this.baseMapper.selectOne(new LambdaQueryWrapper<MemberEntity>()
                .eq(MemberEntity::getSocialUid, uid));
        MemberEntity entity = new MemberEntity();
        if (Objects.nonNull(one)){
            // 用户已经注册了
            // 更新 令牌和时间 并返回用户信息
            entity.setId(one.getId());
            entity.setAccessToken(vo.getAccess_token());
            entity.setExpiresIn(vo.getExpires_in());
            this.updateById(entity);
            one.setAccessToken(vo.getAccess_token());
            one.setExpiresIn(vo.getExpires_in());
            return one;
        }else {
            // 用户第一次登录，需要为他注册
            entity.setSocialUid(vo.getUid());
            entity.setAccessToken(vo.getAccess_token());
            entity.setExpiresIn(vo.getExpires_in());
            // 去社交账号中查询出 用户的社交账号信息。
            Map<String,String> map = new HashMap<>(2);
            map.put("access_token",vo.getAccess_token());
            map.put("uid", vo.getUid());
            try {
                HttpResponse response = HttpUtils.doGet("https://api.weibo.com", "/2/users/show.json",
                        "get", new HashMap<>(1), map);
                if(response.getStatusLine().getStatusCode()==200) {
                    // 查询成功
                    String resp = EntityUtils.toString(response.getEntity());
                    JSONObject jsonObject = JSON.parseObject(resp);
                    String name = jsonObject.getString("name");
                    entity.setNickname(name);
                    entity.setGender("m".equals(jsonObject.getString("gender")) ? 1: 0);
                }else{ log.error("查询社交信息失败"); }
            } catch (Exception e) {
                log.error("调用查询社交信息接口失败！"+ e);
                e.printStackTrace();
            }
            boolean save = this.save(entity);
            if (save) {
                return entity;
            }else {
                log.error("保存用户信息到数据库失败！");
                return null;
            }
        }
    }
}
